from Config import Config, Paths
from transformers import get_linear_schedule_with_warmup, get_cosine_schedule_with_warmup
from sklearn.metrics import roc_auc_score, f1_score, recall_score, precision_score
import random
import os
import numpy as np
import torch

def get_config_dict(config):
    config_dict = dict((key, value) for key, value in config.__dict__.items()
                       if not callable(value) and not key.startswith('__'))
    return config_dict


def get_optimizer_params(model, encoder_lr, decoder_lr, weight_decay=0.0):

    param_optimizer = list(model.named_parameters())

    no_decay = ["bias", "LayerNorm.bias", "LayerNorm.weight"]
    optimizer_parameters = [

        {'params': [p for n, p in model.model.named_parameters() if not any(nd in n for nd in no_decay)],
         'lr': encoder_lr, 'weight_decay': weight_decay},

        {'params': [p for n, p in model.model.named_parameters() if any(nd in n for nd in no_decay)],
         'lr': encoder_lr, 'weight_decay': 0.0},

        {'params': [p for n, p in model.named_parameters() if "model" not in n],
         'lr': decoder_lr, 'weight_decay': 0.0}
    ]
    return optimizer_parameters


def get_logger(filename=Paths.OUTPUT_DIR):
    """创建日志记录器，同时输出到控制台和文件。"""
    from logging import getLogger, INFO, StreamHandler, FileHandler, Formatter

    logger = getLogger(__name__)
    logger.setLevel(INFO) # 设置日志级别


    handler1 = StreamHandler()
    handler1.setFormatter(Formatter("%(message)s"))

    handler2 = FileHandler(filename=f"{filename}.log")
    handler2.setFormatter(Formatter("%(message)s"))

    logger.addHandler(handler1)
    logger.addHandler(handler2)
    return logger

def get_ROC_AUC(y_true, y_pred):
    """计算ROC AUC分数。"""
    score = roc_auc_score(y_true, y_pred)
    return score

def get_F1(y_true, y_prob,threshold):
    y_pred = (y_prob > threshold).astype(int)
    f1 = f1_score(y_true, y_pred)
    return f1


def get_best_F1(y_true, y_prob):
    thresholds = np.linspace(0.3, 0.7, 50)  # 在0.3~0.7之间搜索
    best_threshold = 0.5
    best_f1 = 0

    for thresh in thresholds:
        y_pred = (y_prob > thresh).astype(int)
        f1 = f1_score(y_true, y_pred)
        if f1 > best_f1:
            best_f1 = f1
            best_threshold = thresh
    return best_threshold, best_f1


def get_precision_recall(y_true, pred_probs, threshold=0.5):

    y_pred = np.where(pred_probs > threshold, 1, 0)

    precision = precision_score(y_true, y_pred, pos_label=1)

    recall = recall_score(y_true, y_pred, pos_label=1)
    return precision, recall

def seed_everything(seed=20):
    """设置随机种子确保实验可复现。"""
    random.seed(seed)

    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True


def sep():
    print("-" * 100)


def sigmoid(x):
    return 1 / (1 + np.exp(-x))

LOGGER = get_logger() # 初始化全局日志记录器
seed_everything(seed=Config.SEED) # 设置随机种子（从配置中读取）